using System;
using System.Collections.Generic;

namespace EntityKit.Runtime
{
    public abstract class MvcEntity<T> : Entity where T : MvcEntity<T>
    {
        private List<ModelBase<T>> mModels = new();
        private List<ViewBase<T>> mViews = new();
        private List<ControllerBase<T>> mControllers = new();
        
        public void CollectionChildMVCComponents()
        {
            CollectionComponents();
            mModels = GetEntityComponents<ModelBase<T>>();
            mViews = GetEntityComponents<ViewBase<T>>();
            mControllers = GetEntityComponents<ControllerBase<T>>();
        }

        public void AddModel(ModelBase<T> model)
        {
            if (!mModels.Contains(model))
            {
                mModels.Add(model);
                AddEntityComponent(model);
            }
        }

        public void RemoveModel(ModelBase<T> model)
        {
            if (mModels.Contains(model))
            {
                mModels.Remove(model);
                RemoveEntityComponent(model);
            }
        }
        
        public void RemoveModel<R>() where R : ModelBase<T>
        {
            // 从后向前遍历，避免在遍历时修改列表引发的问题
            for (int i = mModels.Count - 1; i >= 0; i--)
            {
                if (mModels[i] is R)
                {
                    var model = mModels[i];
                    mModels.RemoveAt(i);
                    RemoveEntityComponent(model);
                }
            }
        }

        public R GetModel<R>() where R : ModelBase<T>
        {
            foreach (var model in mModels)
            {
                if (model is R typedModel)
                {
                    return typedModel;
                }
            }

            return null;
        }

        public void AddView(ViewBase<T> view)
        {
            if (!mViews.Contains(view))
            {
                mViews.Add(view);
                AddEntityComponent(view);
            }
        }

        public void RemoveView(ViewBase<T> view)
        {
            if (mViews.Contains(view))
            {
                mViews.Remove(view);
                RemoveEntityComponent(view);
            }
        }

        public void RemoveView<R>() where R : ViewBase<T>
        {
            // 从后向前遍历，避免在遍历时修改列表引发的问题
            for (int i = mViews.Count - 1; i >= 0; i--)
            {
                if (mViews[i] is R)
                {
                    var view = mViews[i];
                    mViews.RemoveAt(i);
                    RemoveEntityComponent(view);
                }
            }
        }

        public R GetView<R>() where R : ViewBase<T>
        {
            foreach (var view in mViews)
            {
                if (view is R typedView)
                {
                    return typedView;
                }
            }
            return null;
        }

        public void AddController(ControllerBase<T> controller)
        {
            if (!mControllers.Contains(controller))
            {
                mControllers.Add(controller);
                AddEntityComponent(controller);
            }
        }

        public void RemoveController(ControllerBase<T> controller)
        {
            if (mControllers.Contains(controller))
            {
                mControllers.Remove(controller);
                RemoveEntityComponent(controller);
            }
        }
        
        public void RemoveController<R>() where R : ControllerBase<T>
        {
            // 从后向前遍历，避免在遍历时修改列表引发的问题
            for (int i = mControllers.Count - 1; i >= 0; i--)
            {
                if (mControllers[i] is R)
                {
                    var controller = mControllers[i];
                    mControllers.RemoveAt(i);
                    RemoveEntityComponent(controller);
                }
            }
        }

        public R GetController<R>() where R : ControllerBase<T>
        {
            foreach (var controller in mControllers)
            {
                if (controller is R typedController)
                {
                    return typedController;
                }
            }

            return null;
        }
    }
}